/*
 * RentalReturnDAO.java
 *
 * Created on April 1, 2007, 2:36 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package finalintex2web;


import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class RentalReturnDAO {
    
    private static RentalReturnDAO rentalReturnDAO = null;
    
    /*
     * Part o the singlteon model, only allows one instance of RentalReturnDAO to exist
     * @returns an instance of RentalReturnDAO
     */
    public static synchronized RentalReturnDAO getInstance() {
        if (rentalReturnDAO == null) {
            rentalReturnDAO = new RentalReturnDAO();
        }
        
        return rentalReturnDAO;
    }
    
    /** Creates a new instance of RentalReturnDAO */
    public RentalReturnDAO() {
    }
    
    
    // CREATE
    ////////////////////////////////////
    
    /*
     * Creates a new RentalReturn object with a new GUID
     * @returns a new RentalReturn
     */
    public RentalReturnBO create() throws UnknownHostException, InterruptedException {
        String id;
        id = GUID.generate();
        RentalReturnBO rentalReturn = new RentalReturnBO(id);
        Cache c = Cache.getInstance();
        c.put(rentalReturn.getId(), rentalReturn);
        //System.out.println(RentalReturn.getId());
        return rentalReturn;
        
    }
    
    // READ
    ////////////////////////////////////
    /*
     * Gets all the RentalReturns in t he database
     *@param conn a Connection to the db
     * @returns a list of all RentalReturns
     */
    public List getAll(Connection conn) throws SQLException, DataException {
        // Create the query
        PreparedStatement query = conn.prepareStatement("SELECT * from rental_return");
        // Run query
        ResultSet rs = query.executeQuery();
        
        List rentalReturns = new ArrayList();
        
        // Loop through result set and create list of RentalReturns in db
        while (rs.next()) {
            String id = rs.getString("id");
            // if the cache already has the RentalReturn object, get it from there
            if (Cache.getInstance().containsKey(id)) {
                rentalReturns.add(Cache.getInstance().get(id));
            } else {
                RentalReturnBO rentalReturn = new RentalReturnBO(id);
                Cache.getInstance().put(id, rentalReturn);
                rentalReturn.setDateIn(new Date(rs.getTimestamp("date_in").getTime()));
                rentalReturn.setDirty(false);
                rentalReturn.setInDB(true);
                rentalReturns.add(rentalReturn);
            }
        }
        
        return rentalReturns;
    }
    
    
    /*
     * Gets one RentalReturn by its pk
     * @param id the pk of the RentalReturn
     * @conn a Connection to the db
     * @returns a new RentalReturn
     */
    public synchronized RentalReturnBO read(String id, Connection conn) throws DataException, SQLException {
        // check again if the id is in the cache, and if so,
        // just get it from the cache.  we need to check again
        // because this method might be called directly from
        // another DAO rather than from read above.
        if (Cache.getInstance().containsKey(id)) {
            return (RentalReturnBO)Cache.getInstance().get(id);
        }
        
        // if not in the cache, get a result set from
        // a SELECT * FROM table WHERE id=guid
        PreparedStatement query = conn.prepareStatement("SELECT * from rental_return where id = ?");
        query.setString(1, id);
        ResultSet rs = query.executeQuery();
        
        RentalReturnBO rentalReturn = null;
        // if the RentalReturn is found, create the corresponding object
        if (rs.next()) {
            rentalReturn = new RentalReturnBO(id);
            Cache cache = Cache.getInstance();
            rentalReturn.setDateIn(new Date(rs.getTimestamp("date_in").getTime()));           
            rentalReturn.setDirty(false);
            // save to the cache
            cache.put(id, rentalReturn);
            
            rentalReturn.setInDB(true);
            
        } else{
            throw new DataException("Object was not found in the database.");
        }
        
        return rentalReturn;
    }
    
    /*
     * Finds a RentalReturn in the db
     * @param id the pk of the RentalReturn
     * @returns a new RentalReturn
     */
    public synchronized RentalReturnBO read(String id) throws DataException, ConnectionPoolException{
        // check to see if id in the cache
        // if so, return it immediately
        if (Cache.getInstance().containsKey(id)) {
            return (RentalReturnBO)Cache.getInstance().get(id);
        }
        
        Connection conn = null;
        RentalReturnBO rentalReturn = null;
        try {
            // retrieve a database connection from the pool
            conn = ConnectionPool.getInstance().get();
            // call read with a connection (the other read method in this class)
            rentalReturn = read(id, conn);
            // release the connection
            ConnectionPool.getInstance().release(conn);
        }catch (SQLException e) {
            try {
                conn.rollback();
            } catch (SQLException xx) {
                xx.printStackTrace();
            }
            throw new DataException("Could not retrieve record for id=" + id, e);
        }
        
        // release the connection back to the pool
        return rentalReturn;
    }
    
    // UPDATE
    ////////////////////////////////////
    
    /*
     * Saves a RentalReturn to the db
     * This gets called by the other save method, which will create the connection to the db if necessary
     * @param RentalReturn the RentalReturn object to be saved
     * @param conn the Connection to the db
     */
    public void save(RentalReturnBO rentalReturn, Connection conn) throws SQLException, DataException, ConnectionPoolException {
        // check the dirty flag in the object.  if it is dirty,
        // run update or insert
        
        // If the object has been modified, save it
        if (rentalReturn.isDirty()) {
            Cache.getInstance().put(rentalReturn.getId(), rentalReturn);
            
            // If it is already in the db, update, otherwise insert
            if (rentalReturn.isInDB()) {
                update(rentalReturn, conn);
            }else{
                insert(rentalReturn, conn);
            }
            rentalReturn.setDirty(false);
            Cache.getInstance().touch(rentalReturn.getId());
        } else {
            System.out.println("Object not set as dirty, not saved");
        }
        
    }
    
    /*
     * Saves a RentalReturn to the database, creates connection to the db if necessary
     * This method calls the other save method
     * @param RentalReturn the RentalReturn to be saved
     */
    public void save(RentalReturnBO rentalReturn) throws DataException, ConnectionPoolException {
        //System.out.println("Saving " + RentalReturn);
        Connection conn = null;
        try {
            // retrieve a database connection from the pool
            conn = ConnectionPool.getInstance().get();
            // call save with a connection (the other save method in this class)
            save(rentalReturn, conn);
            conn.commit();
            // release the connection
            ConnectionPool.getInstance().release(conn);
        }catch (SQLException e) {
            // rollback
            try {
                conn.rollback();
            } catch (SQLException xx) {
                xx.printStackTrace();
            }
            e.printStackTrace();
            throw new DataException("Could not save record for id=" + rentalReturn.getId(), e);
        }
        
    }
    
    /*
     * Inserts a new RentalReturn into the db
     * @param RentalReturn the RentalReturn to be inserted
     * @param conn the Connection to the db
     */
    public void insert(RentalReturnBO rentalReturn, Connection conn) throws SQLException, DataException, ConnectionPoolException {
        // Prepare the sql, load it with the RentalReturn values
        PreparedStatement insert = conn.prepareStatement("INSERT into rental_return (id, date_in, rental_id) values (?,?,?)");
        insert.setString(1, rentalReturn.getId());
        insert.setTimestamp(2, new Timestamp(rentalReturn.getDateIn().getTime()));
        insert.setString(3, rentalReturn.getRentalID());
        
        insert.execute();
    }
    
    /*
     * Updates a RentalReturn already in t he db
     * @param RentalReturn the RentalReturn to be updated
     * @param conn the Connection to the db
     */
    public void update(RentalReturnBO rentalReturn, Connection conn) throws SQLException, DataException, ConnectionPoolException {
        // Prepare the sql, load it with RentalReturn values
        PreparedStatement update = conn.prepareStatement("UPDATE rental_return set date_in = ?, rental_id = ?, where id = ?");
        update.setTimestamp(1, new Timestamp(rentalReturn.getDateIn().getTime()));
        update.setString(2, rentalReturn.getRentalID());
        update.setString(3, rentalReturn.getId());
        
        update.executeUpdate();
    }
    
    // DELETE
    ////////////////////////////////////
    
    // Deletes not implemented since we don't want to blow up RentalReturn records'
    
    
    // SEARCH
    ///////////////////////////////////
    
    
    
}